//=============================================================================
/**
 *
 *	@file		break_kawara.c
 *	@brief		かわらモジュール関連
 *	@author		hosaka genya
 *	@data		2008.11.11
 *
 */
//=============================================================================
#include "common.h"
#include "break_kawara.h"
#include "system/snd_tool.h"
#include "gflib/touchpanel.h"

#include "../event_se_def.h"
#include "break_obj_main_NANR_LBLDEFS.h"

#ifdef PM_DEBUG
	// カワラの補充フレームを表示
//	#define PRINT_KAWARA_MAKE_FRAME
#endif

typedef struct KAWARA_WORK_tag * KAWARA_PTR;

//=============================================================================
/**
 *								定数定義
 */
//=============================================================================

//--------------------------------------------------------------
///	ヒビ エリア座標(中心からの誤差)
//==============================================================
static const s16 c_CrackPos[CRACK_AREA_MAX][2] = {
	{ -12, -12 },	// A
	{ 2, -13 },		// B
	{ -16, -4 },	// C
	{ -2, -4 },		// D
};

//--------------------------------------------------------------
///	Kawara State
//==============================================================
typedef enum {
	K_STATE_NULL = 0,
	K_STATE_MAKE,
	K_STATE_NORMAL,
} K_STATE;

//=============================================================================
/**
 *								構造体定義
 */
//=============================================================================
#define KAWARA_EFF_NUM (16)
//--------------------------------------------------------------
///	かわら破壊エフェクト ワーク
//==============================================================
typedef struct KAWARA_EFF_tag {
	CATS_ACT_PTR capEff;
	BOOL bEnable;
	fx32 SpdX;
	fx32 SpdY;
	s16 PosX;
	s16 PosY;
} KAWARA_EFF;

//--------------------------------------------------------------
///	かわら破壊エフェクト コントロールワーク
//==============================================================
typedef struct KAWARA_EFF_CNT_tag {
	KAWARA_EFF eff[ KAWARA_EFF_NUM ];
} KAWARA_EFF_CNT;

//--------------------------------------------------------------
///	かわらモジュール(自分用)
//==============================================================
typedef struct KAWARA_WORK_tag {
	CATS_ACT_PTR capMain;
	CATS_ACT_PTR capCrack;
	s16 Hp;				///< 耐久度
	s16	CrackAreaPosX;	///< ヒビの座標差分を保持(かわらに対して)
	s16	CrackAreaPosY;	///< ヒビの座標差分を保持(かわらに対して)
	u32	CrackArea : 4;	///< ヒビ位置を保持
	u32 Speed : 8;		///< Y座標 落下速度
	u32 State : 8;		///< かわらの状態
	u32 Idx : 7;		///< 何番目のかわらか
	u32 bEnable : 1;	///< 有効フラグ
	u32 DummyBit : 4;
} KAWARA_WORK;

//--------------------------------------------------------------
///	かわらモジュール(自分用) 管理ワーク
//==============================================================
typedef struct KAWARA_CNT_WORK_tag {
	// [IN]
	PKTHLN_PTR work;
	CATS_SYS_PTR csp;
	CATS_RES_PTR crp;
	// [PRIVATE]
	CATS_ACT_PTR capHit;		///< ヒットエフェクト
	CATS_ACT_PTR capBreak;		///< ヒット破片
	KAWARA_EFF_CNT cntEff;
	KAWARA_PTR Kawara[ KAWARA_NUM ];
	u32		Timer : 16;
	u32		BreakCount : 16;	///< 破壊枚数
	u32		State : 4;			///< 状態
	u32		RestNum : 4;		///< かわら残り枚数
	u32		dummy : 24;
} KAWARA_CNT_WORK;

//=============================================================================
/**
 *							プロトタイプ宣言
 */
//=============================================================================
static void _KawaraCnt_ProcMake( KAWARA_CNT_PTR cnt );
static void _KawaraCnt_ProcNormal( KAWARA_CNT_PTR cnt );
static KAWARA_PTR Kawara_Create( HEAPID HeapID, CATS_SYS_PTR csp, CATS_RES_PTR crp, u16 idx );
static void Kawara_Init( KAWARA_PTR ptr );
static void Kawara_Delete( KAWARA_PTR ptr );
static void Kawara_ProcMake( KAWARA_PTR ptr );
static void Kawara_SetCrackData( KAWARA_PTR ptr );
static void Kawara_SetCrackPos( KAWARA_PTR ptr );
static BOOL Kawara_SetCrackCheck( KAWARA_PTR ptr, BREAK_TEC_LV tecLv );
static void Kawara_GetPos( KAWARA_PTR ptr, s16* px, s16* py );
static K_STATE Kawara_GetState( KAWARA_PTR ptr );
static void KawaraEff_Init( KAWARA_EFF_CNT* cnt, CATS_SYS_PTR csp, CATS_RES_PTR crp );
static void KawaraEff_Delete(KAWARA_EFF_CNT* cnt );
static void KawaraEff_Start( KAWARA_EFF_CNT* cnt, u8 add_num, s16 px, s16 py );
static BOOL KawaraEff_EffMove( KAWARA_EFF* eff );
static void KawaraEff_Proc( KAWARA_EFF_CNT* cnt );
static void KawaraEff_AllAnimeStop( KAWARA_EFF_CNT* cnt );

//=============================================================================
/**
 *								外部公開関数
 */
//=============================================================================

//-----------------------------------------------------------------------------
/**
 *	@brief	かわらコントローラー生成
 *
 *	@param	HEAPID HeapID
 *	@param	csp
 *	@param	crp
 *	@param	work
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
KAWARA_CNT_PTR KawaraCnt_Create( HEAPID HeapID, CATS_SYS_PTR csp, CATS_RES_PTR crp, PKTHLN_PTR work )
{
	int i;
	KAWARA_CNT_PTR cnt;

	cnt = sys_AllocMemory( HeapID, sizeof(KAWARA_CNT_WORK) );
	MI_CpuClear8( cnt, sizeof(KAWARA_CNT_WORK) );

	// 初期化
	cnt->State = KC_STATE_MAKE;
	cnt->RestNum = 0;
	cnt->csp = csp;
	cnt->crp = crp;
	cnt->work = work;

	// ヒットエフェクト CAP生成
	cnt->capHit = OBJ_AddCommon( csp, crp, 0, 0, NANR_break_obj_main_EffHit_S, PRI_HIT_EFF );
	CATS_ObjectEnableCap( cnt->capHit, CATS_ENABLE_FALSE );

	cnt->capBreak = OBJ_AddCommon( csp, crp, 0, 0, NANR_break_obj_main_EffHit_L, PRI_HIT_EFF );
	CATS_ObjectEnableCap( cnt->capBreak, CATS_ENABLE_FALSE );

	// かわら生成
	for( i=0; i<KAWARA_NUM; i++ )
	{
		cnt->Kawara[i] = Kawara_Create( HeapID, csp, crp, i );
	}

	// エフェクト初期化
	KawaraEff_Init( &cnt->cntEff, csp, crp );

	return cnt;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわらコントローラー 削除
 *
 *	@param	KAWARA_CNT_PTR cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void KawaraCnt_Delete( KAWARA_CNT_PTR cnt )
{
	int i;

	GF_ASSERT( cnt );
	GF_ASSERT( cnt->capHit );

	// ACT_PTR開放
	CATS_ActorPointerDelete_S( cnt->capHit );
	CATS_ActorPointerDelete_S( cnt->capBreak );

	for( i=0; i<KAWARA_NUM; i++ )
	{
		Kawara_Delete( cnt->Kawara[i] );
	}

	KawaraEff_Delete( &cnt->cntEff );

	sys_FreeMemoryEz( cnt );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわらコントローラー 主処理
 *
 *	@param	KAWARA_CNT_PTR cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void KawaraCnt_Proc( KAWARA_CNT_PTR cnt )
{
	GF_ASSERT( cnt );

	switch( cnt->State )
	{
		case KC_STATE_MAKE :
			_KawaraCnt_ProcMake( cnt );
			break;

		case KC_STATE_NORMAL :
			_KawaraCnt_ProcNormal( cnt );
			break;

		default : GF_ASSERT(0);
	}

	KawaraEff_Proc( &cnt->cntEff );

#if 0 //PM_DEBUG
	if( sys.trg & PAD_KEY_UP )
	{
		if( cnt->BreakCount < BREAK_COUNT_MAX )
		{
			cnt->BreakCount += 5;
		}
	}
	else if( sys.trg & PAD_KEY_DOWN )
	{
		if( cnt->BreakCount > 5 )
		{
			cnt->BreakCount -= 5;
		}
	}
#endif
}

//-----------------------------------------------------------------------------
/**
 *	@brief	カワラ終了処理
 *
 *	@param	KAWARA_CNT_PTR cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void KawaraCnt_SetEnd( KAWARA_CNT_PTR cnt )
{
	int i;

	CATS_ObjectAutoAnimeSetCap( cnt->capBreak, FALSE );
	CATS_ObjectAutoAnimeSetCap( cnt->capHit, FALSE );

	for( i=0; i<KAWARA_NUM; i++ )
	{
		if( cnt->Kawara[i]->bEnable )
		{
			CATS_ObjectAutoAnimeSetCap( cnt->Kawara[i]->capMain, FALSE );
			CATS_ObjectAutoAnimeSetCap( cnt->Kawara[i]->capCrack, FALSE );
		}
	}

	KawaraEff_AllAnimeStop( &cnt->cntEff );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	ひびチェック(クリティカル判定)
 *
 *	@param	KAWARA_CNT_PTR ptr
 *	@param	tecLv
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
BOOL KawaraCnt_CheckCritical( KAWARA_CNT_PTR cnt, BREAK_TEC_LV tecLv )
{
	GF_ASSERT( cnt );
	GF_ASSERT( cnt->RestNum > 0 );

	if( Kawara_SetCrackCheck( cnt->Kawara[ cnt->RestNum-1 ], tecLv ) )
	{
		HOSAKA_PRINT("Critical!!! \n");
		return TRUE;
	}
	return FALSE;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわらとタッチ座標の当たり判定
 *
 *	@param	KAWARA_CNT_PTR cnt
 *
 *	@retval TRUE:かわらに当たった
 */
//-----------------------------------------------------------------------------
BOOL KawaraCnt_CheckHit( KAWARA_CNT_PTR cnt )
{
	enum {
		DIFF_TOP = -18,	///< かわら中心点からの距離
		DIFF_DOWN = 12,
	};

	static const s16 PosTbl[][2] = {
		// -- 左辺 --
		{ -30, DIFF_DOWN },	//下
		{ -16, DIFF_TOP },	//上
		// -- 右辺 --
		{  16, DIFF_DOWN },	//下
		{  30, DIFF_TOP },	//上
	};

	int i;
	s16 px, py;
	u32 tx, ty;

	GF_ASSERT( cnt );

	// 生成中は常に当たらない
	if( cnt->State == K_STATE_MAKE ){ return FALSE; }

	GF_ASSERT( cnt->RestNum > 0 );

	// かわらの座標を取得
	Kawara_GetPos( cnt->Kawara[ cnt->RestNum-1 ], &px, &py );

	// タッチ座標を取得
	GF_TP_GetPointTrg( &tx, &ty );

	// 上下判定
	if( (ty >= py + DIFF_TOP ) && (ty <= py + DIFF_DOWN) )
	{
		// 左辺、右辺の判定(線分と点の当たり判定)
		VecFx32 VecTP, Vec[4];

		// タッチ座標
		VecTP.x = FX32_CONST(tx);
		VecTP.y = FX32_CONST(ty);

		HOSAKA_PRINT("********* make tbl ********** \n");
		// かわら座標を扱いやすい形に
		for( i=0; i<4; i++ )
		{
			Vec[i].x = FX32_CONST(px + PosTbl[i][0]);
			Vec[i].y = FX32_CONST(py + PosTbl[i][1]);
			HOSAKA_PRINT("{ %d, %d }\n", Vec[i].x>>FX32_SHIFT,Vec[i].y>>FX32_SHIFT);
		}

		{
			fx32 valLeft;
			fx32 valRight;

			//※ Y = A * X + B であるという前提での当たり判定

			// 左辺のY軸について計算
			valLeft = FX_Mul( Vec[1].y - Vec[0].y, VecTP.x - Vec[0].x );
			valLeft = FX_Div( valLeft, Vec[1].x - Vec[0].x );
			valLeft += Vec[0].y;

			// 右辺のY軸について計算
			valRight = FX_Mul( Vec[3].y - Vec[2].y, VecTP.x - Vec[2].x );
			valRight = FX_Div( valRight, Vec[3].x - Vec[2].x );
			valRight += Vec[2].y;

			HOSAKA_PRINT("touch:%d left:%d right:%d \n", VecTP.y>>FX32_SHIFT, valLeft>>FX32_SHIFT, valRight>>FX32_SHIFT);

			// 正方形、左辺、右辺の当たり判定
			if(	( VecTP.x >= Vec[1].x && VecTP.x <= Vec[2].x  ) ||
				( VecTP.y >= valLeft && VecTP.x >= Vec[0].x && VecTP.x <= Vec[1].x ) ||
				( VecTP.y <= valRight && VecTP.x >= Vec[2].x && VecTP.x <= Vec[3].x ) )
			{
				HOSAKA_PRINT("Hit!!\n");
				return TRUE;
			}
		}
	}

	return FALSE;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	カワラコントローラー ダメージ受付
 *
 *	@param	PokeIdx
 *	@param	KAWARA_CNT_PTR cnt
 *	@param	damage
 *	@param	bCritical
 *	@param	bHighTension
 *	@param	outBreakAllFlag
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
u16 KawaraCnt_Damage( KAWARA_CNT_PTR cnt, u8 PokeIdx, s16 damage, BOOL bCritical, BOOL bHighTension, BOOL* outBreakAllFlag )
{
	int i;
	int nowRest;
	u32 tx, ty;
	BOOL breakNum = 0;

	GF_ASSERT(cnt);

	// 既にかわらが無ければ何もしない
	if( cnt->RestNum <= 0 ){ return FALSE; }

	// タッチ座標を取得
	GF_TP_GetPointTrg( &tx, &ty );

	// ヒット エフェクト
	{
		u32 anm = NANR_break_obj_main_EffHit_S;
		CATS_ObjectPosSetCap( cnt->capHit, tx, ty );

		// クリティカルだったら大エフェクト
		if( bCritical || bHighTension ){ anm = NANR_break_obj_main_EffHit_L; }

		CATS_ObjectAnimeSeqSetCap( cnt->capHit, anm );
		CATS_ObjectEnableCap( cnt->capHit, CATS_ENABLE_TRUE );
	}

	if( bHighTension )
	{
		// ハイテンションならダメージUP
		damage += HIGH_TENSION_DAMAGE_PLUS;
		// クリティカル音も鳴らす
		Snd_SePlay( SE_BREAK_CRITICAL );
	}
	else
	{
		if( bCritical )
		{
			// クリティカルダメージ反映
			damage += DAMAGE_CRITICAL;
			Snd_SePlay( SE_BREAK_CRITICAL );
		}
	}

	// 現在のかわら枚数を保持
	nowRest = cnt->RestNum;

	for( i=0; i<nowRest; i++ )
	{
		KAWARA_PTR ptr = cnt->Kawara[ nowRest - (i+1) ];

		// ダメージがなければ
		if( damage <= 0 ){ break; }

		// カワラ 耐久値減算
		ptr->Hp -= damage;

		// 壊れなかった
		if( ptr->Hp > 0 )
		{
			break;
		}
		// 壊れた
		else if( ptr->Hp <= 0 )
		{
			s16 px, py;

			cnt->RestNum--;
			cnt->BreakCount++;
			if( cnt->BreakCount > BREAK_COUNT_MAX ){ cnt->BreakCount = BREAK_COUNT_MAX; }
			CATS_ObjectAnimeSeqSetCap( ptr->capMain, NANR_break_obj_main_Blank );
			CATS_ObjectPosGetCap( ptr->capMain, &px, &py );
			// ヒビ非表示
			CATS_ObjectEnableCap( ptr->capCrack, CATS_ENABLE_FALSE );
			// 余りダメージを反転
			damage = ptr->Hp * -1;
			// 壊れた数を計上
			breakNum++;
			// 壊れエフェクト開始
			KawaraEff_Start( &cnt->cntEff, KAWARA_EFF_ADD_NUM, px, py );
			// AP:ポイント獲得
			PTFrame_AddActionPoint( cnt->work, PTFrameGetCurrentID(cnt->work), PokeIdx, ADD_TYPE_GET, 1 );
		}
	}

	if( breakNum )
	{
		// かわら破壊音
		Snd_SePlay( SE_BREAK_ATTACK04 );
	}
	else
	{
		// かわら攻撃音
		Snd_SePlay( SE_BREAK_ATTACK01 );

		// 破片エフェクト
		CATS_ObjectPosSetCap( cnt->capBreak, tx, ty );
		CATS_ObjectAnimeSeqSetCap( cnt->capBreak, NANR_break_obj_main_EffBreak_L );
		CATS_ObjectEnableCap( cnt->capBreak, CATS_ENABLE_TRUE );
	}

	// 壊れなかった場合の処理
	if( breakNum == 0 && cnt->RestNum > 0 )
	{
		KAWARA_PTR ptr = cnt->Kawara[ cnt->RestNum - 1 ];

		// 状態遷移
		if( ptr->Hp <= KAWARA_ANM_CHG_HP_2 )
		{
			CATS_ObjectAnimeSeqSetCap( ptr->capMain, NANR_break_obj_main_Block2 );
		}
		else if( ptr->Hp <= KAWARA_ANM_CHG_HP_1 )
		{
			CATS_ObjectAnimeSeqSetCap( ptr->capMain, NANR_break_obj_main_Block1 );
			Snd_SePlay( SE_BREAK_ATTACK03 );

			//ピッチを上下半音の幅でランダム
			Snd_PlayerSetTrackPitchBySeqNo( SE_BREAK_ATTACK03, SND_TRACK_BITMASK,
											(64 - (gf_rand() % 128)) );
		}
	}

	// 10枚目を壊した場合はフラグを返す
	*outBreakAllFlag = ( breakNum > 0 && cnt->RestNum == 0 );

	return breakNum;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわらコントローラー 状態取得
 *
 *	@param	KAWARA_CNT_PTR cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
KC_STATE KawaraCnt_GetState( KAWARA_CNT_PTR cnt )
{
	GF_ASSERT( cnt );
	return ( cnt->State );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわらコントローラー 破壊枚数取得
 *
 *	@param	KAWARA_CNT_PTR cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
u16 KawaraCnt_GetBreakCount( KAWARA_CNT_PTR cnt )
{
	GF_ASSERT( cnt );
	return cnt->BreakCount;
}

//=============================================================================
/**
 *								static関数
 */
//=============================================================================

//-----------------------------------------------------------------------------
/**
 *	@brief	かわら生成 PROC
 *
 *	@param	KAWARA_CNT_PTR cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void _KawaraCnt_ProcMake( KAWARA_CNT_PTR cnt )
{
	int i;

#ifdef PRINT_KAWARA_MAKE_FRAME
	static int debug_count = 0;
	debug_count++;
#endif

	// 全てのかわら生成 終了チェック
	if( cnt->RestNum >= KAWARA_NUM )
	{
		for( i=0; i<KAWARA_NUM; i++ )
		{
			if( Kawara_GetState( cnt->Kawara[i] ) == K_STATE_MAKE )
			{
				break;
			}
		}

		if( i == KAWARA_NUM )
		{
			// かわら生成終了
			Snd_SePlay( SE_BREAK_TILE_OK );
			cnt->State = KC_STATE_NORMAL;
#ifdef PRINT_KAWARA_MAKE_FRAME
			HOSAKA_PRINT("かわら補充フレーム:%d \n",debug_count);
			debug_count = 0;
#endif
		}
	}
	else if( cnt->Timer++ >= KAWARA_MAKE_SPAN )
	{
		cnt->Timer = 0;

		Kawara_Init( cnt->Kawara[ cnt->RestNum ] );

		Snd_SePlay( SE_BREAK_TILE_ADD );

		HOSAKA_PRINT("kawara init : %d \n", cnt->RestNum );

		cnt->RestNum++;
	}

	for( i=0; i<KAWARA_NUM; i++ )
	{
		Kawara_ProcMake( cnt->Kawara[i] );
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわら通常 PROC
 *
 *	@param	KAWARA_CNT_PTR cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void _KawaraCnt_ProcNormal( KAWARA_CNT_PTR cnt )
{
	// 全てのかわらを破壊したら生成
	if( cnt->RestNum <= 0 )
	{
		cnt->State = KC_STATE_MAKE;
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわら生成
 *
 *	@param	HEAPID HeapID
 *	@param	csp
 *	@param	crp
 *	@param	idx
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static KAWARA_PTR Kawara_Create( HEAPID HeapID, CATS_SYS_PTR csp, CATS_RES_PTR crp, u16 idx )
{
	KAWARA_PTR ptr;
	GF_ASSERT( csp );
	GF_ASSERT( crp );

	ptr = sys_AllocMemory( HeapID, sizeof(KAWARA_WORK) );
	MI_CpuClear8( ptr, sizeof(KAWARA_WORK) );

	ptr->Idx = idx;

	{
		u16 pri = (PRI_KAWARA_END-1) - (idx)*2;

		// ヒビ CAP生成
		ptr	->capCrack = OBJ_AddCommon( csp, crp, 0, 0, NANR_break_obj_main_Crack, pri );
		CATS_ObjectEnableCap( ptr->capCrack, CATS_ENABLE_FALSE );

		// かわら CAP生成
		ptr->capMain = OBJ_AddCommon( csp, crp, KAWARA_STD_POS_X, 0, NANR_break_obj_main_Block0, pri+1 );
		CATS_ObjectEnableCap( ptr->capMain, CATS_ENABLE_FALSE );
		CATS_ObjectAutoAnimeSetCap( ptr->capMain, TRUE );
	}

	return ptr;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわら初期化
 *
 *	@param	KAWARA_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void Kawara_Init( KAWARA_PTR ptr )
{
	GF_ASSERT( ptr );

	// ※CAPを保持するので、メモリクリアを行っていない。
	ptr->Hp = KAWARA_HP_MAX;
	ptr->Speed = 0;
	ptr->State = K_STATE_MAKE;
	ptr->bEnable = TRUE;

	CATS_ObjectAnimeSeqSetCap( ptr->capMain, NANR_break_obj_main_Block0 );
	CATS_ObjectPosSetCap( ptr->capMain, KAWARA_STD_POS_X, 0 );
	CATS_ObjectEnableCap( ptr->capMain, CATS_ENABLE_TRUE );

	// ヒビ抽選
	Kawara_SetCrackData( ptr );
	Kawara_SetCrackPos( ptr );
	CATS_ObjectEnableCap( ptr->capCrack, CATS_ENABLE_TRUE );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわら削除
 *
 *	@param	KAWARA_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void Kawara_Delete( KAWARA_PTR ptr )
{
	GF_ASSERT( ptr );
	GF_ASSERT( ptr->capMain );
	GF_ASSERT( ptr->capCrack );

	CATS_ActorPointerDelete_S( ptr->capMain );
	CATS_ActorPointerDelete_S( ptr->capCrack );

	sys_FreeMemoryEz( ptr );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわら生成 PROC
 *
 *	@param	KAWARA_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void Kawara_ProcMake( KAWARA_PTR ptr )
{
	s16 nx, ny; ///< now x, y
	u32 tar;

	// 既に生成されていたら強制終了
	if( ptr->State != K_STATE_MAKE ){ return; }

	tar = KAWARA_STD_POS_Y - (ptr->Idx * KAWARA_DOT_HIGHT);

	ptr->Speed += KAWARA_DROP_ACCEL;

	CATS_ObjectPosMoveCap( ptr->capMain, 0, ptr->Speed );
	CATS_ObjectPosMoveCap( ptr->capCrack, 0, ptr->Speed );

	{
		CATS_ObjectPosGetCap( ptr->capCrack, &nx, &ny );
	}

	CATS_ObjectPosGetCap( ptr->capMain, &nx, &ny );

	// 生成完了
	if( ny >= tar )
	{
		ny = tar;
		CATS_ObjectPosSetCap( ptr->capMain, nx, ny );
		Kawara_SetCrackPos( ptr );
		ptr->State = K_STATE_NORMAL;
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	ヒビ抽選
 *
 *	@param	KAWARA_CNT_PTR ptr
 *
 *	@retval
 *
 *	@note	初回はメモリクリアされているので、0が抽選からはずされる
 */
//-----------------------------------------------------------------------------
static void Kawara_SetCrackData( KAWARA_PTR ptr )
{
	u8 rnd;

	GF_ASSERT( ptr );

	// 前回のAreaは抽選からはずす
	rnd = gf_mtRand() % (CRACK_AREA_MAX-1);
	if( rnd >= ptr->CrackArea ){ rnd++; }

	// エリア決定
	ptr->CrackArea = rnd;

	// エリアから座標を抽選
	ptr->CrackAreaPosX = c_CrackPos[ ptr->CrackArea ][0] + gf_mtRand() % CRACK_AREA_X_MAX;
	ptr->CrackAreaPosY = c_CrackPos[ ptr->CrackArea ][1] + gf_mtRand() % CRACK_AREA_Y_MAX;

	HOSAKA_PRINT( "set [%d] crack area : %d \n", ptr->Idx, ptr->CrackArea );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	指定したかわらを基準に座標を設定
 *
 *	@param	KAWARA_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void Kawara_SetCrackPos( KAWARA_PTR ptr )
{
	s16 px, py;

	GF_ASSERT( ptr );

	// かわら座標を取得
	Kawara_GetPos( ptr, &px, &py );

	// エリア座標 計算
	px += ptr->CrackAreaPosX;
	py += ptr->CrackAreaPosY;

	CATS_ObjectPosSetCap( ptr->capCrack, px, py );
}


//-----------------------------------------------------------------------------
/**
 *	@brief 当たり判定テーブルを生成
 *
 *	@param	KAWARA_PTR ptr
 *	@param	tecLv
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static BOOL Kawara_SetCrackCheck( KAWARA_PTR ptr, BREAK_TEC_LV tecLv )
{
	enum {
		HITTBL_LOW_MAX = 3,
		HITTBL_NORMAL_MAX = 3,
		HITTBL_HIGHT_MAX = 3,
		HITTBL_ELEM_MAX = 3,
	};

	/**********************************************
	 * [lv 1]   [lv 2]   [lv 3]
	 * 0 1 0    1 1 1    0 1 1 1 0
	 * 1 1 1  1 1 1 1 1  1 1 1 1 1
	 * 0 1 0    1 1 1    1 1 1 1 1
	 *                   1 1 1 1 1
	 *                   0 1 1 1 0
	 *********************************************/
	// LV 1テーブル
	static const RECT_HIT_TBL HitTbl_Low[ HITTBL_LOW_MAX ] = {
		{ -2, 2, -1, 1, },
		{ -1, 1, -2, 2, },
		{ RECT_HIT_END, 0, 0, 0, },
	};
	// LV 2テーブル
	static const RECT_HIT_TBL HitTbl_Normal[ HITTBL_NORMAL_MAX ] = {
		{ -2, 2, -2, 2, },
		{ -1, 1, -3, 3, },
		{ RECT_HIT_END, 0, 0, 0, },
	};
	// LV 3テーブル
	static const RECT_HIT_TBL HitTbl_Hight[ HITTBL_HIGHT_MAX ] = {
		{ -2, 2, -3, 3, },
		{ -3, 3, -2, 2, },
		{ RECT_HIT_END, 0, 0, 0, },
	};
	// テーブル ポインタリスト
	static const void* pHitTblList[] = {
		&HitTbl_Low,
		&HitTbl_Normal,
		&HitTbl_Hight,
	};
	// 要素数
	static const u8 HitTblNum[] = { HITTBL_LOW_MAX, HITTBL_NORMAL_MAX, HITTBL_HIGHT_MAX };

	int i;
	s16 crack_x, crack_y;
	u8 enable_tbl_num;
	const RECT_HIT_TBL* pTblSrc;
	RECT_HIT_TBL HitTbl[ HITTBL_ELEM_MAX ] = {0};

	GF_ASSERT( tecLv < BREAK_TEC_LV_MAX );

	pTblSrc = (RECT_HIT_TBL*)pHitTblList[ tecLv ];	///< 参照テーブルを決定
	enable_tbl_num= HitTblNum[ tecLv ] - 1;			///< 終焉テーブルを除去したテーブル数

	// 中心座標を取得
	CATS_ObjectPosGetCap( ptr->capCrack, &crack_x, &crack_y );

//	OS_TPrintf( "crack [%d,%d]\n",crack_x, crack_y );

	// テーブルの要素に元々の座標を加算
	for( i=0; i<enable_tbl_num; i++ )
	{
		HitTbl[i].rect.top		= pTblSrc[i].rect.top + crack_y;
		HitTbl[i].rect.bottom	= pTblSrc[i].rect.bottom + crack_y;
		HitTbl[i].rect.left		= pTblSrc[i].rect.left + crack_x;
		HitTbl[i].rect.right	= pTblSrc[i].rect.right + crack_x;

		OS_TPrintf( "x[%d-%d] y[%d-%d] \n",
				HitTbl[i].rect.left, HitTbl[i].rect.right, HitTbl[i].rect.top, HitTbl[i].rect.bottom );
	}

	HitTbl[ enable_tbl_num ].rect.top = RECT_HIT_END;	///< 終焉コードを設定

	OS_TPrintf("touch{%d, %d} tecLv:%d \n",sys.tp_x, sys.tp_y, tecLv);

	return ( GF_TP_RectHitTrg( HitTbl ) != RECT_HIT_NONE );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわらの中心座標を取得
 *
 *	@param	KAWARA_PTR ptr
 *	@param	px
 *	@param	py
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void Kawara_GetPos( KAWARA_PTR ptr, s16* px, s16* py )
{
	GF_ASSERT( ptr );

	CATS_ObjectPosGetCap( ptr->capMain, px, py );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわらの状態を取得
 *
 *	@param	KAWARA_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static K_STATE Kawara_GetState( KAWARA_PTR ptr )
{
	GF_ASSERT( ptr );

	return ptr->State;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわら破壊エフェクト管理モジュール　初期化
 *
 *	@param	KAWARA_EFF_CNT* cnt
 *	@param	csp
 *	@param	crp
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void KawaraEff_Init( KAWARA_EFF_CNT* cnt, CATS_SYS_PTR csp, CATS_RES_PTR crp )
{
	int i;

	for( i=0; i<KAWARA_EFF_NUM; i++ )
	{
		cnt->eff[i].capEff = OBJ_AddCommon( csp, crp, 0, 0, NANR_break_obj_main_EffBreak_L00+(i%3), PRI_HIT_EFF );
		CATS_ObjectEnableCap( cnt->eff[i].capEff, CATS_ENABLE_FALSE );
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわら破壊エフェクト管理モジュール　削除
 *
 *	@param	cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void KawaraEff_Delete(KAWARA_EFF_CNT* cnt )
{
	int i;

	for( i=0; i<KAWARA_EFF_NUM; i++ )
	{
		GF_ASSERT( cnt->eff[i].capEff );
		CATS_ActorPointerDelete_S( cnt->eff[i].capEff );
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわら破壊エフェクト管理モジュール　エフェクトADD
 *
 *	@param	KAWARA_EFF_CNT* cnt
 *	@param	px
 *	@param	py
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void KawaraEff_Start( KAWARA_EFF_CNT* cnt, u8 add_num, s16 px, s16 py )
{
	int i;
	int count = 0;

	for( i=0; i<KAWARA_EFF_NUM; i++ )
	{
		KAWARA_EFF* eff = &cnt->eff[i];

		if( eff->bEnable == FALSE )
		{
			eff->bEnable = TRUE;
			eff->PosX = px;
			eff->PosY = py;
			eff->SpdX = FX32_CONST( 4 + gf_mtRand() % 8 ) * ( i%2 == 0 ? 1 : -1 );
			eff->SpdY = FX32_CONST( 8 + gf_mtRand() % 8 );
			CATS_ObjectPosSetCap( eff->capEff, px, py );
			CATS_ObjectAnimeReStartCap( eff->capEff );
			CATS_ObjectEnableCap( eff->capEff, CATS_ENABLE_TRUE );
			count++;

//			HOSAKA_PRINT("kawaraEff Create:%d \n",i);
		}

		// 指定数用意できたら処理を抜ける
		if( count >= add_num ){ break; }
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわら破壊エフェクト 移動処理
 *
 *	@param	KAWARA_EFF* eff
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static BOOL KawaraEff_EffMove( KAWARA_EFF* eff )
{
	eff->PosX += eff->SpdX >> FX32_SHIFT;
	eff->SpdX = eff->SpdX * 4 / 3;

	eff->PosY -= eff->SpdY >> FX32_SHIFT;
	eff->SpdY -= 4;

	CATS_ObjectPosSetCap( eff->capEff, eff->PosX, eff->PosY );

	if( eff->PosX < 0 || eff->PosX > GX_LCD_SIZE_X )
	{
		return TRUE;
	}

	return FALSE;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	かわら破壊エフェクト管理モジュール　主処理
 *
 *	@param	KAWARA_EFF_CNT* cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void KawaraEff_Proc( KAWARA_EFF_CNT* cnt )
{
	int i;

	for( i=0; i<KAWARA_EFF_NUM; i++ )
	{
		if( cnt->eff[i].bEnable == TRUE )
		{
			if( KawaraEff_EffMove( &cnt->eff[i] ) )
			{
				CATS_ObjectEnableCap( cnt->eff[i].capEff, CATS_ENABLE_FALSE );
				cnt->eff[i].bEnable = FALSE;
				HOSAKA_PRINT("kawaraEff Delete:%d \n",i);
			}
		}
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	カワラエフェクト 全てのアニメーション停止
 *
 *	@param	KAWARA_EFF_CNT* cnt
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void KawaraEff_AllAnimeStop( KAWARA_EFF_CNT* cnt )
{
	int i;

	for( i=0; i<KAWARA_EFF_NUM; i++ )
	{
		if( cnt->eff[i].bEnable == TRUE )
		{
			CATS_ObjectAutoAnimeSetCap( cnt->eff[i].capEff, FALSE );
		}
	}
}

